﻿#include "canthread.h"
#include "ControlCAN.h"
#include <QTime>
#include <QCoreApplication>
#include <QMetaType>
#include <QDebug>
#include <string.h>
#include "quiwidget.h"
#include "parsecandata.h"

VCI_BOARD_INFO vbi;
CANThread::CANThread()
{
    stopped = false;
    qRegisterMetaType<VCI_CAN_OBJ>("VCI_CAN_OBJ");
    qRegisterMetaType<DWORD>("DWORD");
}

void CANThread::stop()
{
    stopped = true;
}

bool CANThread::openCAN(const int &deviceType,const int &debicIndex,const int &baundRate,const int &debicCom)
{
    m_deviceType = deviceType;
    m_debicIndex = debicIndex;
    m_baundRate = baundRate;
    m_debicCom = debicCom;

    int nDeviceType = deviceType;
    int nDeviceInd = debicIndex; /* 第1个设备 */
    int nCANInd = debicCom; /* 第1个通道 */
    DWORD dwRel;
    dwRel = VCI_OpenDevice(nDeviceType, nDeviceInd, nCANInd);
    if(dwRel != 1)
    {
        qCritical()<<"CAN卡打开失败";
        return false;
    }

    dwRel = VCI_ClearBuffer(nDeviceType, nDeviceInd, nCANInd);
    //dwRel = VCI_ClearBuffer(nDeviceType, nDeviceInd, nCANInd+1);
    VCI_INIT_CONFIG vic;
    vic.AccCode=0x00000000;
    vic.AccMask=0xFFFFFFFF;
    vic.Filter=1;
    vic.Mode=0;

    DWORD other_baudRate_type = 0x060007;   //默认500kbps
    switch (baundRate) {
    case 10:
        vic.Timing0=0x31;
        vic.Timing1=0x1c;
        other_baudRate_type = 0x1C00E0;
        break;
    case 20:
        vic.Timing0=0x18;
        vic.Timing1=0x1c;
        other_baudRate_type = 0x1600B3;
        break;
    case 40:
        vic.Timing0=0x87;
        vic.Timing1=0xff;
        break;
    case 50:
        vic.Timing0=0x09;
        vic.Timing1=0x1c;
        other_baudRate_type = 0x1C002C;
        break;
    case 80:
        vic.Timing0=0x83;
        vic.Timing1=0xff;
        break;
    case 100:
        vic.Timing0=0x04;
        vic.Timing1=0x1c;
        other_baudRate_type = 0x160023;
        break;
    case 125:
        vic.Timing0=0x03;
        vic.Timing1=0x1c;
        other_baudRate_type = 0x1C0011;
        break;
    case 200:
        vic.Timing0=0x81;
        vic.Timing1=0xfa;
        break;
    case 250:
        vic.Timing0=0x01;
        vic.Timing1=0x1c;
        other_baudRate_type = 0x1C0008;
        break;
    case 400:
        vic.Timing0=0x80;
        vic.Timing1=0xfa;
        break;
    case 500:
        vic.Timing0=0x00;
        vic.Timing1=0x1c;
        other_baudRate_type = 0x060007;
        break;
    case 666:
        vic.Timing0=0x80;
        vic.Timing1=0xb6;
        break;
    case 800:
        vic.Timing0=0x00;
        vic.Timing1=0x16;
        other_baudRate_type = 0x060004;
        break;
    case 1000:
        vic.Timing0=0x00;
        vic.Timing1=0x14;
        other_baudRate_type = 0x060003;
        break;
    case 33:
        vic.Timing0=0x09;
        vic.Timing1=0x6f;
        break;
    case 66:
        vic.Timing0=0x04;
        vic.Timing1=0x6f;
        break;
    case 83:
        vic.Timing0=0x03;
        vic.Timing1=0x6f;
        break;
    default:
        break;
    }

    if(nDeviceType == VCI_USBCAN_2E_U)
    {
        // 设置波特率（通过 VCI_SetReference）
        //DWORD baudRate = 0x060007;  // 500 kbps（具体值参考设备手册）
        if (VCI_SetReference(nDeviceType, nDeviceInd, nCANInd,0,&other_baudRate_type) != 1)
        {
            qDebug() << "Failed to set baud rate.";
            VCI_CloseDevice(nDeviceType, nDeviceInd);
            return false;
        }
    }

    dwRel = VCI_InitCAN(nDeviceType, nDeviceInd, nCANInd, &vic);
    if(dwRel !=1)
    {
        qCritical() << "CAN卡1初始化失败";
        VCI_CloseDevice(nDeviceType, nDeviceInd);
        return false;
    }

    dwRel = VCI_ReadBoardInfo(nDeviceType, nDeviceInd, &vbi);
    if(dwRel != 1)
    {
//        qDebug()<<"get dev message fail:"<<MB_OK<<MB_ICONQUESTION;
        return false;
    }
    else
    {
        qDebug()<<"CAN通道数："<<vbi.can_Num;
        qDebug()<<"硬件版本号:"<<vbi.hw_Version;
        qDebug()<<"接口库版本号："<<vbi.in_Version;
        qDebug()<<"中断号"<<vbi.irq_Num;
    }

    if(VCI_StartCAN(nDeviceType, nDeviceInd, nCANInd) !=1)
    {
        qDebug()<<"start"<<nCANInd<<"fail";
        return false;
    }
    else
        qDebug()<<"start"<<nCANInd<<"success:";

    return true;
}

void CANThread::closeCAN()
{
    VCI_CloseDevice(m_deviceType, m_debicIndex);

    qInfo() << "设备关闭成功";
}

void CANThread::sendData(int ID,const QByteArray &data)
{
    // 1. 校验数据长度
    int dataSize = data.size();
    if(dataSize < 8) {
        qCritical() << "数据长度不足8字节";
        return;
    }

    DWORD dwRel;
    VCI_CAN_OBJ vco{};

    vco.ID = ID ;
    vco.RemoteFlag = 0;
    vco.ExternFlag = 0;
    vco.DataLen = 8;
    // 安全拷贝数据（避免越界）
    BytefromQByteArray(data,vco.Data);

    qDebug() << "原始数据:" << BytetoQByteArray(vco.Data,8).toHex();

    dwRel = VCI_Transmit(m_deviceType, m_debicIndex, m_debicCom, &vco,1);
    if(dwRel>0) {
        qDebug() << "成功发送" << dwRel << "帧 | ID:" << Qt::hex << ID << "数据:" << data.toHex();
    } else {
        qCritical() << "发送失败 | 错误码:" << dwRel; //
    }

}

QByteArray CANThread::BytetoQByteArray(const BYTE *data, int size)
{
    return QByteArray(reinterpret_cast<const char*>(data), size);
}

void CANThread::BytefromQByteArray(const QByteArray &src, BYTE *dest)
{
    std::copy_n(reinterpret_cast<const BYTE*>(src.constData()), src.size(), dest);
}

void CANThread::run()
{
    while(!stopped)
    {
        int len = VCI_GetReceiveNum(m_deviceType,m_debicIndex,m_debicCom);
        //qDebug() << "当前未读取的帧长度：" << len;

        QMutex mutex;
        mutex.lock();
        DWORD dwRel;
        VCI_CAN_OBJ vco[2500];
        dwRel = VCI_Receive(m_deviceType, m_debicIndex, m_debicCom, vco,2500,0);
        if(dwRel > 0)
        {            
            int ID;
            for (DWORD i = 0; i < dwRel; i++) {
                ID = vco[i].ID;
                QStringList strframes;
                for (int j = 0; j < vco[i].DataLen; j++) {
                    QString str = QString::number(vco[i].Data[j],16);
                    if(str.length() < 2) {
                        str = "0" + str;
                    }
                    strframes.push_back(str);
                }

                m_mutex.lock();
                if(ID == QUIHelper::strHexToDecimal("0x204")) {
                    ParseCANDataIns->parseBMS204(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x208")) {
                    ParseCANDataIns->parseBMS208(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x36A")) {
                    ParseCANDataIns->parseBMS36A(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x36B")) {
                    ParseCANDataIns->parseBMS36B(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x35A")) {
                    ParseCANDataIns->parseBMS35A(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x39B")) {
                    ParseCANDataIns->parseBMS39B(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x253")) {
                    ParseCANDataIns->parseVCU253(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x205")) {
                    ParseCANDataIns->parseBMS205(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x38A")) {
                    ParseCANDataIns->parseBMS38A(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x39A")) {
                    ParseCANDataIns->parseBMS39A(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x37B")) {
                    ParseCANDataIns->parseBMS37B(strframes);
                }
                else if(ID == QUIHelper::strHexToDecimal("0x3E4")) {
                    ParseCANDataIns->parseBMS3E4(strframes);
                }
                m_mutex.unlock();
            }
        }
        else if(dwRel == -1)
        {
        /* USB-CAN设备不存在或USB掉线，可以调用VCI_CloseDevice并重新
        VCI_OpenDevice。如此可以达到USB-CAN设备热插拔的效果。 */
            qDebug()<<"设备不存在或USB掉线";
//            VCI_CloseDevice(deviceType, debicIndex);
//            VCI_OpenDevice(deviceType, debicIndex, debicCom);
        }
        //sleep(1000);

        mutex.unlock();
    }
    stopped = false;
}

void CANThread::sleep(unsigned int msec)
{
   QTime dieTime = QTime::currentTime().addMSecs(msec);
   while( QTime::currentTime() < dieTime )
       QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
